
<template>
  <div class="app-container" :style="backgroundDiv">
  <div class="hea1" style="padding: 20px;">
    <h3 style="font-size: 30px;text-align: center" >中文语音识别</h3>
    <br>
    <div style="font-size: 14px">
      <h3>录音时长:{{ recorder && recorder.duration.toFixed(4) }}</h3>
      <el-button type="primary" @click="handleStart" >开始录音</el-button>
      <el-button type="warning" @click="handlePause">暂停录音</el-button>
      <el-button type="success" @click="handleResume">继续录音</el-button>
      <el-button type="warning" @click="handleStop">停止录音</el-button>
      <br><br>
      <h3>
        播放时长:{{
          recorder &&
          (playTime > recorder.duration
              ? recorder.duration.toFixed(4)
              : playTime.toFixed(4))
        }}
      </h3>
      <audio ref="audios" :src="this.audio" controls ></audio>
      <br />
      <br>
      <h3 style="font-size: 16px ">上传本地文件:</h3>
      <div>
        <input type="file"  value="" id="file" @change="uploadConfig">
        <button @click="upload">上传该文件</button>
      </div>
      <br><br>
      <div class="bo">

        <el-button type="primary" @click="handleDestroy">销毁录音</el-button>

        <el-button type="success" @click="getResults">识别结果</el-button>
      </div>

      <br />
      <br />
      <textarea
          name=""
          id="textarea"
          style="width: 100%; height: 100px;border: solid 1px lightblue"
          cols="30"
          rows="10"
          v-model="result"
      />
    </div>
  </div>
  </div>
</template>

<script>
import Recorder from 'js-audio-recorder'
import { v4 as uuidv4 } from "uuid";
import axios from 'axios';
uuidv4();

export default {
  data(){
    return {
      backgroundDiv:{
        backgroundImage:'url('+require('@/assets/img.png')+')',
        backgroundRepeat:'no-repeat',
        backgroundSize: '100% 100%'
      },
      recorder: null,
      playTime: 0,
      timer: null,
      src: null,
      sessionId: "",
      audio: "",
      data: "",
      result: "",
      formdata: null,
      URL: '/api/lang/',
      Config: {
        headers:{'Content-Type':'multipart/form-data'}
      },
    };
  },
  created() {},
  mounted() {
    this.dataRecorder = this.data;
  },

  methods: {
    // 开始录音
    handleStart() {
      const uuid = require("uuid");
      this.sessionId = uuid.v4();
      console.log(this.sessionId);

      this.recorder = new Recorder({
        sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
        sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
        numChannels: 1, // 声道，支持 1 或 2， 默认是1
        // compiling: false,(0.x版本中生效,1.x增加中)  // 是否边录边转换，默认是false
      });
      console.log(this.recorder)
      Recorder.getPermission().then(
          () => {
            console.log("开始录音");

            this.recorder.start(); // 开始录音
          },
          (error) => {
            this.$message({
              message: "请先允许该网页使用麦克风",
              type: "info",
            });
            console.log(`${error.name} : ${error.message}`);
          }
      );
    },
    // 暂停录音
    handlePause() {
      console.log("暂停录音");
      this.recorder.pause(); // 暂停录音
    },
    // 继续录音
    handleResume() {
      console.log("恢复录音");
      this.recorder.resume(); // 恢复录音
    },
    //停止录音
    handleStop() {
      console.log("停止录音");
      this.recorder.stop(); // 停止录音
      this.handlePlay();  //
    },

    // 播放录音模块
    handlePlay() {
      console.log("播放录音");
      console.log(this.recorder);
      const bl = this.recorder.getWAVBlob()
      const r = new FileReader();
      r.readAsArrayBuffer(bl);
      r.onload = (e) => {
        const bufer = e.srcElement.result;
        const b = this.addWavHeader(bufer, 16000, 16, 1);
        this.audio = window.URL.createObjectURL(b);
      };


      console.log(this.$refs.audios);
      //  this.recorder.play(); // 播放录音

      // 播放时长
      this.timer = setInterval(() => {
        try {
          this.playTime = this.recorder.getPlayTime();
        } catch (error) {
          this.timer = null;
        }
      }, 100);
    },
    addWavHeader(samples, sampleRateTmp, sampleBits, channelCount) {
      const dataLength = samples.byteLength;
      /* 新的buffer类，预留44bytes的heaer空间 */
      const buffer = new ArrayBuffer(44 + dataLength);
      /* 转为 Dataview, 利用API来填充字节 */
      const view = new DataView(buffer);
      let offset = 0;
      /* ChunkID, 4 bytes,  资源交换文件标识符 */
      this.writeString(view, offset, 'RIFF');
      offset += 4;
      /* ChunkSize, 4 bytes, 下个地址开始到文件尾总字节数,即文件大小-8 */
      view.setUint32(offset, /* 32 */ 36 + dataLength, true);
      offset += 4;
      /* Format, 4 bytes, WAV文件标志 */
      this.writeString(view, offset, 'WAVE');
      offset += 4;
      /* Subchunk1 ID, 4 bytes, 波形格式标志 */
      this.writeString(view, offset, 'fmt ');
      offset += 4;
      /* Subchunk1 Size, 4 bytes, 过滤字节,一般为 0x10 = 16 */
      view.setUint32(offset, 16, true);
      offset += 4;
      /* Audio Format, 2 bytes, 格式类别 (PCM形式采样数据) */
      view.setUint16(offset, 1, true);
      offset += 2;
      /* Num Channels, 2 bytes,  通道数 */
      view.setUint16(offset, channelCount, true);
      offset += 2;
      /* SampleRate, 4 bytes, 采样率,每秒样本数,表示每个通道的播放速度 */
      view.setUint32(offset, sampleRateTmp, true);
      offset += 4;
      /* ByteRate, 4 bytes, 波形数据传输率 (每秒平均字节数) 通道数×每秒数据位数×每样本数据位/8 */
      view.setUint32(offset, sampleRateTmp * channelCount * (sampleBits / 8), true);
      offset += 4;
      /* BlockAlign, 2 bytes, 快数据调整数 采样一次占用字节数 通道数×每样本的数据位数/8 */
      view.setUint16(offset, channelCount * (sampleBits / 8), true);
      offset += 2;
      /* BitsPerSample, 2 bytes, 每样本数据位数 */
      view.setUint16(offset, sampleBits, true);
      offset += 2;
      /* Subchunk2 ID, 4 bytes, 数据标识符 */
      this.writeString(view, offset, 'data');
      offset += 4;
      /* Subchunk2 Size, 4 bytes, 采样数据总数,即数据总大小-44 */
      view.setUint32(offset, dataLength, true);
      offset += 4;
      if (sampleBits === 16) {
        this.floatTo16BitPCM(view, samples);
      } else if (sampleBits === 8) {
        this.floatTo8BitPCM(view, samples);
      } else {
        this.floatTo32BitPCM(view, samples);
      }
      return new Blob([view], {type: 'audio/wav'});
    },
    writeString(view, offset, string) {
      for (let i = 0; i < string.length; i += 1) {
        view.setUint8(offset + i, string.charCodeAt(i));
      }
    },
    floatTo32BitPCM(output, input) {
      const oinput = new Int32Array(input);
      let newoffset = 44;
      for (let i = 0; i < oinput.length; i += 1, newoffset += 4) {
        output.setInt32(newoffset, oinput[i], true);
      }
    },
    floatTo16BitPCM(output, input) {
      const oinput = new Int16Array(input);
      let newoffset = 44;
      for (let i = 0; i < oinput.length; i += 1, newoffset += 2) {
        output.setInt16(newoffset, oinput[i], true);
      }
    },
    floatTo8BitPCM(output, input) {
      const oinput = new Int8Array(input);
      let newoffset = 44;
      for (let i = 0; i < oinput.length; i += 1, newoffset += 1) {
        output.setInt8(newoffset, oinput[i], true);
      }
    },



    uploadConfig(e) {
      let formData = new FormData();

      formData.append('filename', e.target.files[0]);
      formData.append('data', 'hello');   // 上传文件的同时， 也可以上传其他数据

      this.formdata=formData

    },
    upload(){
      let formData=this.formdata
      let url=this.URL
      let config=this.Config
      console.log(url)
      console.log(config)
      console.log(formData)
      if(this.formdata==null){
        this.$message({
          message: "未选择任何文件",
          type: "error",
        });
        return false;
      }
      this.axios.post(url,formData, config).then(function (response) {
        console.log(response.data)
        this.result = response.data.word;
      })
    },

    handleDestroy() {
      console.log("销毁实例");
      this.recorder.destroy(); // 毁实例
      this.timer = null;
    },

    //识别结果
    getResults() {
      if (this.recorder == null || this.recorder.duration === 0) {
        this.$message({
          message: "请先录音或上传音频文件",
          type: "error",
        });
        return false;
      }
      this.recorder.pause(); // 暂停录音
      this.timer = null;
      console.log("上传录音"); // 上传录音

      const formData = new FormData();
      const blob = this.recorder.getWAVBlob(); // 获取wav格式音频数据
      console.log(blob);
      // 此处获取到blob对象后需要设置fileName满足当前项目上传需求，可直接传把blob作为file塞入formData
      const newbolb = new Blob([blob], {type: "audio/wav"});
      const fileOfBlob = new File([newbolb], new Date().getTime() + ".wav");
      console.log(fileOfBlob);
      formData.append("filename", fileOfBlob);
      console.log(formData);
      formData.append("data", 'hello test');
      const url = window.URL.createObjectURL(fileOfBlob);
      this.src = url;
      console.log(url);
      this.axios({
        url: '/api/lang/',
        //url: this.baseURL + '/putAudio?asrType=non_real&sessionId=' + this.sessionID,
        method: "post",
        headers: this.Config,
        data: formData,
      }).then(function (res) {
        if (res.status === 200) {
          this.result = res.data.word;
          alert("上传完成可以识别");

        } else {
          alert("上传失败请重试");
        }
      });
      //console.log("识别结果");
      // this.axios({
      //   url: "https://10.85.134.230:8899/asr/non_real/getResult",
      //   method: "get",
      //   params: {
      //     sessionId: this.sessionId,
      //   }
      // }).then((response) => (this.result = response.data));

    },


  }
}

</script>
<style scoped>

.hea1 {
  line-height: 20px;
  color: aliceblue;
}
/*.bo {*/
/*  display: flex;*/
/*  justify-content: space-between;*/
/*  flex:1*/
/*}*/
</style>